#include <os/list.h>
#include <os/sched.h>
#include <type.h>

uint64_t time_elapsed = 0;
uint64_t time_base = 0;

uint64_t get_ticks()
{
    __asm__ __volatile__(
        "rdtime %0"
        : "=r"(time_elapsed));
    return time_elapsed;
}

uint64_t get_timer()
{
    return get_ticks() / time_base;
}

uint64_t get_time_base()
{
    return time_base;
}

void latency(uint64_t time)
{
    uint64_t begin_time = get_timer();

    while (get_timer() - begin_time < time);
    return;
}

static inline int if_queue_empty(list_head * l)
{
    return((l->prev == l) && (l->next == l));
}

static inline list_node_t * Dequeue(list_head * l)
{
    list_node_t * tail = l->prev;
    list_node_t * head = l->next;
    if((tail == l) && (head == l))
    {
        //如果队列为空
        return NULL;
    }
    else if(head == tail){
        //只有1个元素
        l->prev = l->next = l;
        return head;
    }
    else{
        //队列原本有元素
        //队头元素出队
        list_node_t * pre = head->prev;
        pre->next = l;
        l->next = pre;
        return head;
    }
}
static inline void Enqueue(list_head * l, list_node_t * new_node)
{
    list_node_t * tail = l->prev;
    list_node_t * head = l->next;
    if((tail == l) && (head == l))
    {
        //如果队列原本为空
        l->prev = l->next = new_node;
        new_node->prev = new_node->next = l;
    }
    else{
        //队列原本有元素
        //新元素入队尾
        l->prev = new_node;
        new_node->next = tail;
        new_node->prev = l;
        tail->prev = new_node;
    }
}

void check_sleeping(void)
{
    // TODO: [p2-task3] Pick out tasks that should wake up from the sleep queue
    list_node_t * tail = sleep_queue.prev;

    while(!if_queue_empty(&sleep_queue))
    {
        list_node_t * node = Dequeue(&sleep_queue);
        pcb_t * pcb = list_entry(node, pcb_t, list);
        if(get_timer() >= pcb->wakeup_time)
        {
            //已达到唤醒时间，令其加入ready_queue
            pcb->status = TASK_READY;
            pcb->wakeup_time = 0;
            // Enqueue(&ready_queue, node);
            enqueue(&ready_queue, pcb);
        }
        else
        {
            //尚未达到时间，重新加入sleep_queue
            enqueue(&sleep_queue, pcb);
        }

        if(node == tail)
        {
            //已完成一个循环
            break;
        }
    }

}